﻿/*----------------------------------------------------------------
 * 
 * 版权所有：Copyright (C) 2013
 * 
 * 文件名：PredicateExtension.cs
 * 文件功能描述：
 * 
 * 
 * 作 者：zhangq
 * 邮 箱：ifunnyface@outlook.com
 * 日 期：2013-01-08 10:23:49
 * 
 * 
 * 修改标识： Author
 * 修改描述： 相关描述
 * 
 * ---------------------------------------------------------------- */

using System;
using System.Linq;
using System.Linq.Expressions;

namespace Water.Core
{

    public static class PredicateExtension
    {

        /// <summary>
        /// 初始为True
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static Expression<Func<T, bool>> True<T>() 
        { 
            return f => true;
        }


        /// <summary>
        /// 初始为Flase
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static Expression<Func<T, bool>> False<T>() { return f => false; }


        /// <summary>
        /// 或者
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="firstExpression"></param>
        /// <param name="secondExpression"></param>
        /// <returns></returns>
        public static Expression<Func<T, bool>> OrElse<T>(
            this Expression<Func<T, bool>> firstExpression,
            Expression<Func<T, bool>> secondExpression)
        {
            firstExpression = firstExpression ?? PredicateExtension.True<T>();
            var invokedExpression = Expression.Invoke(
                        secondExpression,
                        firstExpression.Parameters.Cast<Expression>()
                    );

            return Expression.Lambda<Func<T, bool>>(
                        Expression.OrElse(firstExpression.Body, invokedExpression),
                        firstExpression.Parameters
                    );
        }


        /// <summary>
        /// 并且
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="firstExpression"></param>
        /// <param name="secondExpression"></param>
        /// <returns></returns>
        public static Expression<Func<T, bool>> AndAlso<T>(
            this Expression<Func<T, bool>> firstExpression,
            Expression<Func<T, bool>> secondExpression)
        {
            firstExpression = firstExpression ?? PredicateExtension.True<T>();
            var invokedExpression = Expression.Invoke(
                        secondExpression,
                        firstExpression.Parameters.Cast<Expression>()
                   );

            return Expression.Lambda<Func<T, bool>>(
                        Expression.AndAlso(firstExpression.Body, invokedExpression),
                        firstExpression.Parameters
                    );

        }

    }

}